package itea.bignews.feed;

import itea.bignews.News;
import static itea.bignews.sys.Static.nextSeq;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

/**
 * 
 * @version $Id: FeedFetcher.java 60 2009-11-23 15:31:42Z iteahere $
 * @author itea
 * @date 2009-9-16
 */
public class FeedFetcher {

	protected final Log log = LogFactory.getLog(this.getClass());
	
	protected String feedUrl;

	protected Set<String> oldEntryURIs = new HashSet<String>();
	
	protected ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("javascript");
	
	private String entryConvertScript;
	
	public News convert2news(SyndEntry entry) throws ScriptException {
		Bindings b = jsEngine.createBindings();
		b.put("entry", entry);
		News n = (News) jsEngine.eval(entryConvertScript, b);
		n.setId(nextSeq());
		return n;
	}
	
	public synchronized Collection<News> fetchNewEntries() {
		return fetchNewEntries(feedUrl);
	}
	
	public synchronized Collection<News> fetchNewEntries(String url) {
		Collection<News> rv = new ArrayList<News>();
		Set<String> uris = new HashSet<String>();
		try {
			for(SyndEntry e : fetchFeedEntries(url)) {
				uris.add(e.getLink());
				if(!oldEntryURIs.contains(e.getLink())) {
					News n = convert2news(e);
					rv.add(n);
				}
			}
			oldEntryURIs = uris;
			return rv;
		} catch (Exception e) {
			log.error(e.toString() +": "+ entryConvertScript, e);
			return Collections.<News>emptySet();
		}
	}
	
	public Collection<News> fetchEntries(String url) {
		Collection<News> rv = new ArrayList<News>();
		try {
			for(SyndEntry e : fetchFeedEntries(url)) {
				News n = convert2news(e);
				rv.add(n);
			}
			return rv;
		} catch (Exception e) {
			log.error(e.toString() +": "+ entryConvertScript, e);
			return Collections.<News>emptySet();
		}
	}
	
	public SyndFeed fetchFeed(String url) {
		try {
            SyndFeedInput input = new SyndFeedInput();
            SyndFeed feed = input.build(new XmlReader(new URL(url)));
            return feed;
		} catch (Exception e) {
			log.warn("fetch feed failed: "+ url, e);
        }
		return null;
	}
	
	public Collection<SyndEntry> fetchFeedEntries(String url) {
		try {
            SyndFeedInput input = new SyndFeedInput();
            SyndFeed feed = input.build(new XmlReader(new URL(url)));
            return feed.getEntries();
		} catch (Exception e) {
			log.warn("fetch feed failed: "+ url, e);
        }
		return Collections.<SyndEntry>emptySet();
	}
	
	public void setFeedUrl(String feedUrl) {
		this.feedUrl = feedUrl;
	}

	public String getFeedUrl() {
		return feedUrl;
	}

	public String getEntryConvertScript() {
		return entryConvertScript;
	}

	public void setEntryConvertScript(String script) {
		this.entryConvertScript = script;
	}

	public Set<String> getOldEntryURIs() {
		return oldEntryURIs;
	}

	public void setOldEntryURIs(Set<String> oldEntryURIs) {
		this.oldEntryURIs = oldEntryURIs;
	}
	
}
